﻿using CustomPixelShaderEffect.UlitFolder;
using Microsoft.Graphics.Canvas.Effects;
using Microsoft.Graphics.Canvas;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Navigation;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Storage.Streams;
using Windows.Storage;
using System.Numerics;
using Windows.UI;
using Microsoft.Graphics.Canvas.Brushes;
using Microsoft.Graphics.Canvas.UI.Xaml;
using Microsoft.UI;
using CustomPixelShaderEffect.AttributeUsageFloder;

// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.

namespace CustomPixelShaderEffect.views
{
    [PageType("渐变映射")]
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class GradientMappingPage : Page
    {
        //渐变映射效果
        PixelShaderEffect effect;
        //源图
        CanvasBitmap bitmap;
        //渐变图
        CanvasRenderTarget gradientMap;
        //效果渲染图
        CanvasRenderTarget render;
        //渐变颜色列表
        Color[] colorMap;
        public GradientMappingPage()
        {
            this.InitializeComponent();
            Init();
        }

        void Init()
        {
            canvas.CreateResources += async (s, e) =>
            {
                //获取着色器二进制文件
                StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Shaders/GradientMappingEffect.bin"));
                IBuffer buffer = await FileIO.ReadBufferAsync(file);
                //转换成字节数组
                var bytes = buffer.ToArray();
                //用 字节数组 初始化一个 PixelShaderEffect 对象；
                effect = new PixelShaderEffect(bytes);
                //初始化渐变位图
                gradientMap = new CanvasRenderTarget(canvas, 255, 1, 96);
                colorMap = CreateGradientColors();
                CreateGradientRender(colorMap);
            };

            //选择图片
            selectPicture.Click += async (s, e) =>
            {
                var file = await Ulit.SelectFileAsync(new List<string> { ".png", ".jpg" });
                if (file == null)
                {
                    render = null;
                    bitmap = null;
                }
                else
                {
                    bitmap = await CanvasBitmap.LoadAsync(canvas.Device, await file.OpenAsync(FileAccessMode.Read));
                    //创建一个与源图大小一样的幕后绘制画布；用于存放绘制效果；
                    render = new CanvasRenderTarget(canvas, bitmap.Size);
                }
                canvas.Invalidate();
            };

            canvas.Draw += (s, e) =>
            {
                //绘制黑白网格
                Win2dUlit.DrawGridGraphics(e.DrawingSession, 100);
                //判断effect 和位图是否为空
                if (effect == null || bitmap == null)
                    return;
                var element = (FrameworkElement)s;
                float effectWidth = (float)element.ActualWidth;
                float effectHeight = (float)element.ActualHeight * 0.6f;
                float previewWidth = effectWidth;
                float previewHeight = (float)element.ActualHeight * 0.3f;
                //设置两张位图源
                effect.Source1 = bitmap;
                effect.Source2 = gradientMap;
                //设置映射图采样为 邻近采样，（默认为线性采样，效果会表现出意料之外）
                effect.Source2Interpolation = CanvasImageInterpolation.NearestNeighbor;
               //将效果绘制到render上
                using (var ds = render.CreateDrawingSession())
                {
                    ds.Clear(Colors.Transparent);
                    ds.DrawImage(effect);
                }
                ////绘制效果图到画布上
                var effectTran = Win2dUlit.CalcutateImageCenteredTransform(effectWidth, effectHeight, bitmap.Size.Width, bitmap.Size.Height);
                effectTran.Source = render;
                //直接将效果绘制到画布上，错误效果
                //var effectTran = Win2dUlit.CalcutateImageCenteredTransform(effectWidth, effectHeight, bitmap.Size.Width, bitmap.Size.Height);
                //effectTran.Source = effect;
                //e.DrawingSession.DrawImage(effectTran);

                //绘制原图
                var previewTran = Win2dUlit.CalcutateImageCenteredTransform(previewWidth, previewHeight, bitmap.Size.Width, bitmap.Size.Height);
                previewTran.Source = bitmap;
                e.DrawingSession.DrawImage(previewTran, 0, effectHeight);
                //绘制渐变图
                var gradientTran = Win2dUlit.CalcutateImageCenteredTransform(effectWidth, element.ActualHeight * 0.1, gradientMap.Size.Width, gradientMap.Size.Height);
                gradientTran.Source = gradientMap;
                var rect = new Rect(0, previewHeight + effectHeight, effectWidth, element.ActualHeight * 0.1);
                e.DrawingSession.DrawImage(gradientMap, rect);
            };

            createGradient.Click += (s, e) =>
            {
                colorMap = CreateGradientColors();
                CreateGradientRender(colorMap);
                canvas.Invalidate();
            };

        }
        /// <summary>
        /// 创建渐变颜色数组
        /// </summary>
        /// <returns></returns>
        Color[] CreateGradientColors()
        {
            var count = Random.Shared.Next(3, 10);
            var colors = new Color[count];
            for (int i = 0; i < count; i++)
            {
                var r = (byte)Random.Shared.Next(255);
                var g = (byte)Random.Shared.Next(255);
                var b = (byte)Random.Shared.Next(255);
                colors[i] = Color.FromArgb(255, r, g, b);
            }
            return colors;
        }

        /// <summary>
        /// 绘制渐变位图
        /// </summary>
        /// <param name="mapColors"></param>
        void CreateGradientRender(Color[] mapColors)
        {
            using (var ds = gradientMap.CreateDrawingSession())
            {
                var canvasGradienStop = new CanvasGradientStop[mapColors.Length];
                for (int i = 0; i < mapColors.Length; i++)
                {
                    canvasGradienStop[i] = new CanvasGradientStop
                    {
                        Color = mapColors[i],
                        Position = (float)i / (float)(mapColors.Length - 1)
                    };
                }
                CanvasLinearGradientBrush linearBrush = new CanvasLinearGradientBrush(gradientMap.Device, canvasGradienStop)
                {
                    StartPoint = new Vector2(0, 0),
                    EndPoint = new Vector2(256, 0),
                };
                ds.FillRectangle(0, 0, 256, 1, linearBrush);
            }
        }
    }
}
